package com.itheima.thread.forkjoin;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;

/**
 * @program: Multhread
 * @description: 这个是任务拆分和合并
 * @author: zhanghz001
 * @create: 2021-03-05 11:09
 **/
@Slf4j
public class AddTask extends RecursiveTask<Integer> {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ForkJoinPool forkJoinPool = new ForkJoinPool(5);
        ForkJoinTask<Integer> task = forkJoinPool.submit(new AddTask(0, 1000));
        System.out.println(task.get());
    }
    
    private static final int MAX = 100;
    private Integer start;
    private Integer end;
    
    public AddTask(Integer start, Integer end) {
        this.start = start;
        this.end = end;
    }
    
    @Override
    protected Integer compute() {
        if (end - start < MAX) {
            log.info("开始计算start: {},end :{} ", start, end);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //小于边界，开始计算
            int total = 0;
            for (int i = start; i <= end; i++) {
                total += i;
            }
            log.info("结束计算 {},结果为: {} ", (this.start + end) / 2, total);
            return total;
        } else {
            long start = System.currentTimeMillis();
            
            log.info("开始拆分 start: {},end :{} ", this.start, end);
            //否则,需要劈开继续拆分
            AddTask task1 = new AddTask(this.start, (this.start + end) / 2);
            task1.fork();
            AddTask task2 = new AddTask((this.start + end) / 2 + 1, end);
            task2.fork();
            long end1 = System.currentTimeMillis();
            log.info("结束拆分 start: {},end :{} ,用时:{}ms", this.start, end, end1 - start);
            
            int i = task1.join() + task2.join();
            long end2 = System.currentTimeMillis();
            log.info("结束执行 start: {},end :{} ,用时:{}ms", this.start, end, end2 - start);
            return i;
        }
    }
}
